﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using DBSourceToolsLib.Suggestions;
//using HCCodeParser.Suggestions;

namespace DBSourceToolsLib.Composite
{
    public class DBComposite : IDBComposite
    {
        HashSet<IDBComposite> m_listChildren = new HashSet<IDBComposite>();
        private TreeNodeTag m_TreeNodeTag;
        public TreeNodeTag GetTreeNodeTag() { return m_TreeNodeTag; }
        private DBCompositeType m_DBCompositeType;
        
        string m_strName;
        string m_strShortName;

        public DBComposite(string strName, string strShortName, DBCompositeType oType, TreeNodeTag oTreeNodeTag)
        {
            m_strName = strName;
            m_strShortName = strShortName;
            m_TreeNodeTag = oTreeNodeTag;
            m_DBCompositeType = oType;
        }

        public bool IsLeaf()
        {
            return m_listChildren.Count > 0;
        }

        public void Add(IDBComposite oDBComposite)
        {
            m_listChildren.Add(oDBComposite);
        }

        public IEnumerator<IDBComposite> GetEnumerator()
        {
            return m_listChildren.GetEnumerator();
        }

        public string GetName()
        {
            return m_strName;
        }


        public string GetShortName()
        {
            if (m_strShortName.Contains(' '))
                return "[" + m_strShortName + "]";
            else
                return m_strShortName;
        }

        public string GetDebugString(int iTabCount)
        {
            StringBuilder oBuilder = new StringBuilder();
            string strTabs = "";
            for (int i = 0; i < iTabCount; i++)
                strTabs += '\t';
            oBuilder.AppendLine(strTabs + GetName());
            oBuilder.AppendLine(strTabs + "k:" + m_TreeNodeTag.GetTreeNodekey());

            foreach (IDBComposite oChildComposite in m_listChildren)
                oBuilder.Append(oChildComposite.GetDebugString(iTabCount + 1));

            return oBuilder.ToString();
        }

        public List<string> BuildTypeKeys(DBCompositeType oDBCType)
        {
            List<string> strKeys = new List<string>();
            if (this.m_DBCompositeType == oDBCType) {
                strKeys.Add(this.GetTreeNodeTag().GetTreeNodekey());
            }
            foreach (IDBComposite oChildComposite in m_listChildren)
            {
                foreach( string strKey in oChildComposite.BuildTypeKeys(oDBCType))
                    strKeys.Add(strKey);
            }
            return strKeys;
        }


        public List<Suggestion> BuildList(FieldListType oFieldListType, params DBCompositeType[] oDBCTypes)
        {
            List<Suggestion> strKeys = new List<Suggestion>();
            foreach (DBCompositeType oType in oDBCTypes)
            {
                if (this.m_DBCompositeType == oType)
                {
                    string strListName = "";
                    switch (oFieldListType)
                    {
                        case FieldListType.Short:
                            strListName = this.GetShortName();
                            break;
                        case FieldListType.Long:
                            strListName = this.GetName();
                            break;
                        case FieldListType.ShortNoSchema:
                            strListName = this.GetShortName();
                            break;
                    }
                    strKeys.Add(new Suggestion (strListName, oType));
                }
            }
            foreach (IDBComposite oChildComposite in m_listChildren)
            {
                foreach (Suggestion strKey in oChildComposite.BuildList(oFieldListType, oDBCTypes))
                    strKeys.Add(strKey);
            }
            return strKeys;
        }

        public List<Suggestion> BuildFieldList(List<TableAndAlias> lstNames)
        {
            List<Suggestion> strFields = new List<Suggestion>();
            if (lstNames.Count < 1)
                return strFields;
            Dictionary<string, List<TableAndAlias>> oDictTableAndAlias = new Dictionary<string, List<TableAndAlias>>();
            //Hashtable oHashTable  = new Hashtable();
            foreach (TableAndAlias oTableAndAlias in lstNames)
            {
                if (!oDictTableAndAlias.ContainsKey(oTableAndAlias.TableName.ToLower()))
                {
                    List<TableAndAlias> oTableAndAliasList = new List<TableAndAlias>();
                    oTableAndAliasList.Add(oTableAndAlias);
                    oDictTableAndAlias.Add(oTableAndAlias.TableName.ToLower(), oTableAndAliasList);
                }
                else
                {
                    List<TableAndAlias> oTableAndAliasList = oDictTableAndAlias[oTableAndAlias.TableName.ToLower()];
                    oTableAndAliasList.Add(oTableAndAlias);
                }
            }

            if ((m_DBCompositeType == DBCompositeType.Table) ||
                (m_DBCompositeType == DBCompositeType.View))
            {
                if (oDictTableAndAlias.ContainsKey(this.GetName().ToLower()))
                {
                    List<TableAndAlias> oMatchedAliasList = oDictTableAndAlias[this.GetName().ToLower()];
                    foreach (TableAndAlias oMatchedAlias in oMatchedAliasList)
                    {
                        foreach (IDBComposite oChildComposite in m_listChildren)
                        {
                            foreach (Suggestion strKey in oChildComposite.BuildList(FieldListType.Short, DBCompositeType.Field))
                            {
                                if (lstNames.Count == 1)
                                {
                                    if (oMatchedAlias.AliasName == null)
                                        strFields.Add(strKey);
                                    else
                                        strFields.Add(new
                                        Suggestion((oMatchedAlias.AliasName + "." + strKey.Name), oChildComposite.GetDBCompositeType()));
                                }
                                else
                                {
                                    if (!String.IsNullOrEmpty(oMatchedAlias.AliasName))
                                        strFields.Add(new Suggestion((oMatchedAlias.AliasName + "." + strKey.Name), oChildComposite.GetDBCompositeType()));
                                    else
                                        strFields.Add(new Suggestion(
                                            (this.GetShortName() + "." + strKey.Name), oChildComposite.GetDBCompositeType()));
                                }
                            }
                        }
                    }
                }
            }

            foreach (IDBComposite oChildComposite in m_listChildren)
            {
                foreach (Suggestion strKey in oChildComposite.BuildFieldList(lstNames))
                    strFields.Add(strKey);
            }

            return strFields;
        }


        public DBCompositeType GetDBCompositeType()
        {
            return this.m_DBCompositeType;
        }
    }
}
